﻿#include<stdexcept>
#include<string>
#include"Fragment.hpp"


namespace MMF { namespace BSpline {


    Fragment::Fragment()
        : mStartPos(0.0f)
        , mLength(0.0f)
    {

    }

    Fragment::Fragment(float startPos, const std::vector<TesVector3>& pts)
        : mStartPos(startPos)
        , mLinesLen(3)
    {
        //贝塞尔三阶点数应为4
        if (pts.size() != 4)
            throw std::length_error((__FILE__ +  std::to_string(__LINE__)).c_str());

        mPoints = pts;

        //计算总长度
        CalcLength();
    }

    float Fragment::CalcLength()
    {
        for (size_t i = 0; i < mPoints.size(); i++)
        {
            if (i > 0)
            {
                float len = (mPoints[i] - mPoints[i - 1]).Length();
                if (i > 1)
                    mLinesLen[i - 1] = mLinesLen[i - 2] + len;
                else
                    mLinesLen[i - 1] = len;
                mLength += len;
            }
        }

        return mLength;
    }

    TesVector3 Fragment::GetPoint(float distance)
    {
        TesVector3 ret = {};

        //剩余长度
        float delatLen = distance - mStartPos;

        //计算t
        float t = delatLen / mLength;

        //拟合
        ret =   mPoints[0] * (1.0f - t) * (1.0f - t) * (1.0f - t) +
                mPoints[1] * (1.0f - t) * (1.0f - t) * t * 3 + 
                mPoints[2] * (1.0f - t) * t * t * 3 + 
                mPoints[3] * t * t * t;

        return ret;
    }

    bool Fragment::isIn(float distance)
    {
        if (distance >= mStartPos && distance <= mStartPos + mLength)
            return true;
            
        return false;
    }
}}